<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/602498 (zh-CN, DDL); Windows/10.0.0 (Win64); EDAMVersion=V2;"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="636"/>

<div>
<span><div><div><span style="font-size: 24pt; color: rgb(255, 0, 0); font-family: 华文楷体;">SpringBoot</span></div><div><br/></div><div><br/></div><div>Spring Boot 是所有基于 Spring 开发的项目的起点。Spring Boot 的设计是为了让你尽可能快的跑起来 Spring 应用程序并且尽可能减少你的配置文件。</div><div><br/></div><div>约定优于配置，又称按约定编程，是一种软件设计范式。</div><div>简单来说就是在编码过程中要遵循约定</div><div><br/></div><div><br/></div><div>Spring Boot概念：</div><div><br/></div><div>spring优缺点分析</div><div>优点：Spring是Java企业版（Java Enterprise Edition，JEE，也称J2EE）的轻量级代替品。无需开发重量级的 Enterprise Java Bean（EJB），Spring为企业级Java开发提供了一种相对简单的方法，通过依赖注入和 面向切面编程，用简单的Java对象（Plain Old Java Object，POJO）实现了EJB的功能</div><div>缺点： </div><ol><li><div>Spring的组件代码是轻量级的，但它的配置却是重量级的</div></li><li><div>项目的依赖管理是一件耗时耗力的事情。</div></li><li><div>SSM整合：Spring、Spring MVC、Mybatis、Spring-Mybatis整合包、数据库驱动，引入依赖的数量繁 多、容易存在版本冲突。</div></li></ol><div><br/></div><div>SpringBoot对上述Spring的缺点进行的改善和优化，基于约定优于配置的思想，可以让开发人员不必在 配置与逻辑 业务之间进行思维的切换，全身心的投入到逻辑业务的代码编写中，从而大大提高了开发的 效率，一定程度上缩短 了项目周期。</div><div><br/></div><div>起步依赖： 本质上是一个Maven项目对象模型(Project Object Model，POM)，定义了对其他库的传递依 赖，这些东西加在一起即支持某项功能。 简单的说，起步依赖就是将具备某种功能的依赖坐标打包到一起，并提供一些默认的功能。</div><div><br/></div><div>自动配置： 指的是springboot，会自动将一些配置类的bean注册进ioc容器，我们可以需 要的地方使用@autowired或者@resource等注解来使用它。</div><div><br/></div><div>“自动”的表现形式就是我们只需要引我们想用功能的包，相关的配置我们完全不用管，springboot会自 动注入这些配置bean，我们直接使用这些bean即可</div><div>springboot: 简单、快速、方便地搭建项目；对主流开发框架的无配置集成；极大提高了开发、部署效率</div><div><br/></div><div>SpringBoot的启动类通常放在二级包中，比如：com.lagou.SpringBootDemo1Application， 因为SpringBoot项目在做包扫描，会扫描启动类所在的包及其子包下的所有内容。</div><div>@SpringBootApplication： 标识当前类为SpringBoot项目的启动类</div><div><br/></div><div>使用Spring Initializr方式搭建的Spring Boot项目，会自动加入spring-boot-starter-test测试依赖 启动器，无需再手动添加</div><div><br/></div><div>@RunWith(SpringRunner.class) //@RunWith:运行器</div><div>SpringJUnit4ClassRunner.class:Spring运行环境</div><div>JUnit4.class:JUnit运行环境</div><div>SpringRunner.class:Spring Boot运行环境</div><div>@SpringBootTest //标记为当前类为SpringBoot测试类，加载项目的ApplicationContext上下文环境</div><div><br/></div><div><br/></div><div>全局配置文件： 全局配置文件能够对一些默认配置值进行修改。Spring Boot使用一个application.properties或者 application.yaml或者application.yml的文件作为全局配置文件，该文件存放在src/main/resource目录或者类路径的/config，一般会选择resource目录。</div><div>Spring Boot配置文件的命名及其格式：</div><ol><li><div>application.properties</div></li><li><div>application.yaml</div></li><li><div>application.yml</div></li></ol><div>在application.properties文件中定义Spring Boot项目的相关属性,这些相关属性可以是系统属性、环境变量、命令参数等信息，也可以是自定义配置文件名称和位置</div><div><br/></div><div>@ConfigurationProperties(prefix = &quot;&quot;)注解的作用是将配置文件中以person开头的属性值通过 setXX()方法注入到实体类对应属性中</div><div>@Component注解的作用是将当前注入属性值的XX类对象作为Bean组件放到Spring容器中，只有 这样才能被@ConfigurationProperties注解进行赋值</div><div><br/></div><div>application.yaml配置文件: YAML文件格式是Spring Boot支持的一种JSON文件格式，相较于传统的Properties配置文件，YAML文件以数据为核心，是一种更为直观且容易被电脑识别的数据序列化格式。application.yaml配置文件的工作原理和application.properties相同，但是yaml格式配置文件会更简洁。</div><div>YAML文件的扩展名可以使用.yml或者.yaml。</div><div>application.yml文件使用 “key:（空格）value格式配置属性，使用缩进控制层级关系。</div><div>SpringBoot的三种配置文件是可以共存的</div><div><br/></div><div><br/></div><div>yaml针对不同数据类型的属性值： value值为普通数据类型（例如数字、字符串、布尔等） 当YAML配置文件中配置的属性值为普通数据类型时，可以直接配置对应的属性值，同时对于字符 串类型的属性值，不需要额外添加引号</div><div>当YAML配置文件中配置的属性值为数组或单列集合类型时，主要有两种书写方式：缩进式写法和行内式写法。</div><div>缩进式写法还有两种表示形式  </div><div>例如：person:                    或者                    person:</div><div>                hobby:                                                hobby:</div><div>                    -  play                                                    play,</div><div>                    -  read                                                    read,</div><div>                    -  sleep                                                    sleep</div><div>上述实例代码中，在YAML配置文件中通过两种缩进式写法对person对象的单列集合（或数组）类型的爱好hobby赋值为play、read和sleep。其中一种形式为“-（空格）属性值”，另一种形式为多个属性值之前加 英文逗号分隔（注意：最后一个属性值后不要加逗号）。</div><div><br/></div><div>value值为Map集合和对象</div><div>当YAML配置文件中配置的属性值为Map集合或对象类型时，YAML配置文件格式同样可以分为两种书写 方式：缩进式写法和行内式写法。</div><div><br/></div><div>缩进式写法的示例代码：                             行内式写法示例代码:</div><div>         person:                                                                 person:</div><div>                map:                                                                    person: map: {k1: v1,k2: v2}</div><div>                     k1:  <span style="font-size: unset; color: unset; font-family: unset;"> </span><span style="font-size: unset; color: unset; font-family: unset;">v1</span></div><div><span style="font-size: unset; color: unset; font-family: unset;">                     k2:   v2 </span></div><div><span style="font-size: unset;"><br/></span></div><div><span style="font-size: unset;"><br/></span></div><div><span style="font-size: unset;"><br/></span></div><div><span style="font-size: unset;"><br/></span></div><div>配置文件属性值的注入</div><div>配置文件的优先级: **/application*.yml&lt; **/application*.yaml&lt; **/application*.properties</div><div><br/></div><div>使用Spring Boot全局配置文件设置属性时： 如果配置属性是Spring Boot已有属性，例如服务端口server.port，那么Spring Boot内部会自动扫描并 读取这些配置文件中的属性值并覆盖默认属性。 如果配置的属性是用户自定义属性，例如自定义的Person实体类属性，还必须在程序中注入这些配置属性方可生效。 Spring Boot支持多种注入配置文件属性的方式</div><div><br/></div><div>使用@ConfigurationProperties注入属性: Spring Boot提供的该注解用来快速、方便地将配置文件中的自定义属性值批量注入到某个Bean对象的多个对应属性中。</div><div>例如： @ConfigurationProperties(prefix = &quot;person&quot;)</div><ol><li><div>将配置文件中所有以person开头的配置信息注入当前类中</div></li><li><div>前提1：必须保证配置文件中person.xx与当前Person类的属性名一致</div></li><li><div>前提2：必须保证当前Person中的属性都具有set方法</div></li></ol><div>使用@Component和@ConfigurationProperties(prefix = “XX”)将配置文件中的每个属性映射到XX类组件中</div><div>使用@Value注入属性： @Value注解是Spring框架提供的，用来读取配置文件中的属性值并逐个注入到Bean对象的对应属性 中，Spring Boot框架从Spring框架中对@Value注解进行了默认继承，所以在Spring Boot框架中还可以 使用该注解读取和注入配置文件属性值。</div><div>例如： <span style="color: rgb(227, 0, 0);">@Component  + @Value(&quot;${person.id}&quot;)</span>   意思时： 使用@Component和@Value注入Person实体类的id属性。其中，@Value不仅可以 将配置文件的属性注入Person的id属性，还可以直接给id属性赋值，这点是@ConfigurationProperties 不支持的</div><div>使用@Value注解方式需要对每一个属性注入设置，同时又免去了属性的 setXX()方法</div><div>注意： @Value注解对于包含Map集合、对象以及YAML文件格式的行内式写法的配置文件的属性注入都不支持，如果赋值会出现错误</div><div><br/></div><div>加载自定义配置文件的需求，可以使用@PropertySource注解来实现。它用于指定自定义配置文件的具体位置和名称，如果需要将自定义配置文件中的属性值注入到对应类的属性中，可以使用 @ConfigurationProperties或者@Value注解进行属性值注入  </div><div>例如： @PropertySource(&quot;classpath:test.properties&quot;) 指定了自定义配置文件的位置和名称，此示例 表示自定义配置文件为classpath类路径下的test.properties文件；</div><div>@ConfigurationProperties(prefix = &quot;test&quot;)注解将上述自定义配置文件test.properties中以test开 头的属性值注入到该配置类属性中。(在类上添加注解时)</div><div><br/></div><div>在Spring Boot框架中，通常使用@Configuration注解定义一个配置类，Spring Boot会自动扫描和识别 配置类，从而替换传统Spring框架中的XML配置文件。</div><div>当定义一个配置类后，还需要在类中的方法上使用@Bean注解进行组件配置，将方法的返回对象注入到 Spring容器中，并且组件名称默认使用的是方法名，当然也可以使用@Bean注解的name或value属性自 定义组件的名称</div><div><br/></div><div>SpringBoot原理：</div><div>Spring Boot程序中，项目pom.xml文件有两个核心依赖，分别是spring-boot-starterparent和spring-boot-starter-web</div><div>spring-boot-starter-parent依赖： 作为Spring Boot项目的统一父项目依赖管理， spring-boot- starter-parent的底层有一个父依赖spring-boot-dependencies该父依赖， 一些常用技术框架的依赖文件进 行了统一版本号管理，例如activemq、spring、tomcat等，都有与Spring Boot 2.2.2版本相匹配的版 本，这也是pom.xml引入依赖文件不需要标注依赖文件版本号的原因。</div><div>注意： 如果pom.xml引入的依赖文件不是 spring-boot-starter-parent管理的，那么在 pom.xml引入依赖文件时，需要使用标签指定依赖文件的版本号。</div><div><br/></div><div>spring-boot-starter-web依赖：</div><div>spring-boot-starter-web依赖启动器的主要作用是提供Web开发场景所需的底层 所有依赖</div><div>在pom.xml中引入spring-boot-starter-web依赖启动器时，就可以实现Web场景开发，而不 需要额外导入Tomcat服务器以及其他Web依赖文件等。当然，这些引入的依赖文件的版本号还是由 spring-boot-starter-parent父依赖进行的统一管理。</div><div><br/></div><div>注意： 在pom.xml文件中引入第三方的依赖启动器时，需要配置对应的版本号</div><div><br/></div><div>自动配置：</div><div>概念： 能够在我们添加jar包依赖的时候，自动为我们配置一些组件的相关配置，我们无需配置或者只需 要少量配置就能运行编写的项目</div><div><br/></div><div>Spring Boot到底是如何进行自动配置的，都把哪些组件进行了自动配置？</div><div>Spring Boot应用的启动入口是@SpringBootApplication注解标注类中的main()方法，</div><div>@SpringBootApplication ： SpringBoot 应用标注在某个类上说明这个类是 SpringBoot 的主配置 类， SpringBoot 就应该运行这个类的 main() 方法启动 SpringBoot 应用。</div><div>@SpringBootConfiguration注解: @SpringBootConfiguration ： SpringBoot 的配置类，标注在某个类上，表示这是一个 SpringBoot 的配置类。</div><div>@SpringBootConfiguration注解内部有一个核心注解@Configuration，该 注解是Spring框架提供的，表示当前类为一个配置类（XML配置文件的注解表现形式），并可以被组件 扫描器扫描。由此可见，@SpringBootConfiguration注解的作用与@Configuration注解相同，都是 标识一个可以被组件扫描器扫描的配置类，只不过@SpringBootConfiguration是被Spring Boot进行 了重新封装命名而已</div><div><br/></div><div>@EnableAutoConfiguration注解: 开启自动配置功能，以前由我们需要配置的东西，现在由 SpringBoot 帮我们自动配置，这个注解就是 Springboot 能实现自动配置的关键。</div><div><br/></div><div>Spring 中有很多以 Enable 开头的注解，其作用就是借助 @Import 来收集并注册特定场景相关的 Bean ，并加载到 IOC 容器。@EnableAutoConfiguration就是借助 @Import来收集所有符合自动配置条件的bean定义，并加载到IoC容器。</div><div><br/></div><div><br/></div><div>@AutoConfigurationPackage注解: @AutoConfigurationPackage注解的功能是由@Import注解实现的，它是 spring框架的底层注解，它的作用就是给容器中导入某个组件类, ，例如 @Import(AutoConfigurationPackages.Registrar.class)，它就是将Registrar这个组件类导入到容器 中，可查看Registrar类中registerBeanDefinitions方法，这个方法就是导入组件类的具体实现 :</div><div><br/></div><div>springboot底层实现自动配置的步骤是：</div><ol><li><div>springboot应用启动；</div></li><li><div>@SpringBootApplication起作用；</div></li><li><div>@EnableAutoConfiguration；</div></li><li><div>@AutoConfigurationPackage：这个组合注解主要是 @Import(AutoConfigurationPackages.Registrar.class)，它通过将Registrar类导入到容器中，而 Registrar类作用是扫描主配置类同级目录以及子包，并将相应的组件导入到springboot创建管理的 容器中；</div></li><li><div>@Import(AutoConfigurationImportSelector.class)：它通过将AutoConfigurationImportSelector 类导入到容器中，AutoConfigurationImportSelector类作用是通过selectImports方法执行的过程 中，会使用内部工具类SpringFactoriesLoader，查找classpath上所有jar包中的METAINF/spring.factories进行加载，实现将配置类信息交给SpringFactory加载器进行一系列的容器创 建过程</div></li></ol><div><br/></div><div>@ComponentScan注解: 具体扫描的包的根路径由Spring Boot项目主程序启动类所在包位置决定， 在扫描过程中由前面介绍的@AutoConfigurationPackage注解进行解析，从而得到Spring Boot项目主 程序启动类所在包的具体位置</div><div><br/></div><div>@SpringBootApplication  简单来说就是 3 个注解的组合注解：</div><div><br/></div><div><br/></div><div>Spring Boot整合MyBatis: 主要是引入对应的依赖启动器，并进行数据库相关参数设置即可，<span style="font-size: unset; color: unset; font-family: unset;">在application.properties配置文件中进行数据库连接配置,在mapper中使用编写sql语句</span></div><div><br/></div><div>注解方式实现整合Spring Boot整合MyBatis</div><ol><li><div>在Spring Boot项目启动类上添加@MapperScan(&quot;xxx&quot;)注解  xxx=mapper的包路径</div></li></ol><div><br/></div><div>为了解决上述由于驼峰命名方式造成的表字段值无法正确映射到类属性的情况，可以在Spring Boot全局 配置文件application.properties中添加开启驼峰命名匹配映射配置</div><div><img src="SpringBoot&SpringCloud_files/Image.png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div>配置文件的方式整合MyBatis： </div><ol><li><div>创建XML映射文件， resources目录下创建一个统一管理映射文件的包mapper，并在该包下编写与ArticleMapper接口方 应的映射文件ArticleMapper.xml</div></li><li><div>配置XML映射文件路径 在项目中编写的XML映射文件，Spring Boot并无从知晓，所以无法扫描到该自定义编写的XML配置文 件，还必须在全局配置文件application.properties中添加MyBatis映射文件路径的配置，同时需要添加 实体类别名映射路径，示例代码如下</div></li></ol><div><br/></div><div><img src="SpringBoot&SpringCloud_files/Image [1].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div>Spring Boot整合Redis：</div><ol><li><div>添加Redis依赖包</div></li><li><div>配置Redis数据库连接</div></li><li><div><img src="SpringBoot&SpringCloud_files/Image [2].png" type="image/png" data-filename="Image.png"/></div></li></ol><div>4. 编写Redis操作工具类</div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>SpringBoot视图技术：</div><div>Spring Boot不太支持常用的JSP模板，并且没有提供对应的整合配置，这是因为使用嵌入式Servlet容 器的Spring Boot应用程序对于JSP模板存在一些限制 ：</div><ol><li><div>在Jetty和Tomcat容器中，Spring Boot应用被打包成war文件可以支持JSP。但Spring Boot默认使 用嵌入式Servlet容器以JAR包方式进行项目打包部署，这种JAR包方式不支持JSP。</div></li><li><div>如果使用Undertow嵌入式容器部署Spring Boot项目，也不支持JSP模板。（Undertow 是红帽公 司开发的一款基于 NIO 的高性能 Web 嵌入式服务器）</div></li><li><div>Spring Boot默认提供了一个处理请求路径“/error”的统一错误处理器，返回具体的异常信息。使用 JSP模板时，无法对默认的错误处理器进行覆盖，只能根据Spring Boot要求在指定位置定制错误页 面。</div></li></ol><div><br/></div><div>Thymeleaf： 是一种现代的基于服务器端的Java模板引擎技术，也是一个优秀的面向Java的XML、 XHTML、HTML5页面模板，它具有丰富的标签语言、函数和表达式，在使用Spring Boot框架进行页面 设计时，一般会选择Thymeleaf模板</div><div><br/></div><div>Thymeleaf的常用标签：</div><div><img src="SpringBoot&SpringCloud_files/Image [3].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div>Thymeleaf的 标准表达式</div><div><img src="SpringBoot&SpringCloud_files/Image [4].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div>变量表达式 ${...}： 主要用于获取上下文中的变量值   例如：<img src="SpringBoot&SpringCloud_files/Image [5].png" type="image/png" data-filename="Image.png"/></div><div>选择变量表达式 *{...} 和变量表达式用法类似，一般用于从被选定对象而不是上下文中获取属性值，如果 没有选定对象，则和变量表达式一样<img src="SpringBoot&SpringCloud_files/Image [6].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div>消息表达式 #{...}： 主要用于Thymeleaf模板页面国际化内容的动态替换和展示，使用消息表达式#{...} 进行国际化设置时，还需要提供一些国际化配置文件</div><div>主要用于Thymeleaf模板页面国际化内容的动态替换和展示，使用消息表达式#{...} 进行国际化设置时，还需要提供一些国际化配置文件</div><div>片段表达式~{...}用来标记一个片段模板，并根据需要移动或传递给其他模板。其中，最常见的用法是使 用th:insert或th:replace属性插入片段</div><div><br/></div><div><br/></div><div>Spring Boot项目部署：</div><ol><li><div>添加打包组件</div></li><li><div>部署运行： java -jar 包名</div></li></ol><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><span style="color: rgb(255, 0, 0); font-family: 华文楷体; font-size: 24pt;">Spring Cloud 微服务</span></div><div><br/></div><div><br/></div><div><br/></div><div>单体应用架构项目所有的功能模块都放在一个工程中编码、 编译、打包并且部署在一个Tomcat容器中的架构模式就是单体应用架构，这样的架构既简单实 ⽤、便 于维护，成本⼜低</div><div>优点：</div><ol><li><div>高效开发：项⽬前期开发节奏快，团队成员少的时候能够快速迭代</div></li><li><div>架构简单：MVC架构，只需要借助IDE开发、调试即可</div></li><li><div>易于测试：只需要通过单元测试或者浏览器完成</div></li><li><div>易于部署：打包成单⼀可执⾏的jar或者打成war包放到容器内启动</div></li></ol><div>缺点：</div><ol><li><div>可靠性差： 某个应用Bug，例如死循环、内存溢出等， 可能会导致整个应用的崩溃</div></li><li><div>复杂性高： 以一个百万行级别的单体应用为例，整个项目包含的模块多、模块的边界模糊、 依赖 关系不清晰、 代码质量参差不齐、 混乱地堆砌在一起。使得整个项目非常复杂。</div></li><li><div>扩展能力受限： 单体应用只能作为一个整体进行扩展，无法根据业务模块的需要进行伸缩。例如， 应用中有的模块是计算密集型的，它需要强劲的CPU； 有的模块则是IO密集型的，需要更大的内 存。 由于这些模块部署在一起，不得不在硬件的选择上做出妥协。</div></li></ol><div><br/></div><div><br/></div><div>垂直应用架构： 核心目标标第⼀个是为了业务之间互不影响，第⼆个是在研发团队的壮⼤后为了提⾼效率， 减少组件之间的依赖。</div><div>优点：</div><ol><li><div>系统拆分实现了流量分担，解决了并发问题</div></li><li><div>可以针对不同模块进⾏优化</div></li><li><div>⽅便⽔平扩展，负载均衡，容错率提⾼</div></li><li><div>系统间相互独⽴，互不影响，新的业务迭代时更加⾼效</div></li></ol><div>缺点：</div><ol><li><div>服务之间相互调⽤，如果某个服务的端⼝或者ip地址发⽣改变，调⽤的系统得⼿动改变</div></li><li><div>搭建集群之后，实现负载均衡⽐较复杂，如：内⽹负载，在迁移机器时会影响调⽤⽅的路 由，导致 线上故障</div></li><li><div>服务之间调⽤⽅式不统⼀，基于 httpclient 、 webservice ，接⼝协议不统⼀</div></li><li><div>服务监控不到位：除了依靠端⼝、进程的监控，调⽤的成功率、失败率、总耗时等等这些监 控指标 是没有的</div></li></ol><div><br/></div><div><br/></div><div>SOA应用架构： 即面向服务的架构。根据实际业务，把系统拆分成合适 的、独立部署的模块，模块之间相互独立（通过Webservice/Dubbo等技术进行通信）。</div><div>优点：</div><ol><li><div>优点：分布式、松耦合、扩展灵活、可重用。</div></li><li><div>缺点：服务抽取粒度较大、服务调用方和提供方耦合度较高（接口耦合度）</div></li></ol><div><br/></div><div><br/></div><div>微服务应用架构： 可以说是SOA架构的一种拓展，这种架构模式下它拆分粒度更小、服务更独立。把应用 拆分成为一个个微小的服务，不同的服务可以使用不同的开发语言和存储，服务之间往往通过Restful等 轻量级通信。微服务架构关键在于微小、独立、轻量级通信。</div><div>微服务是在 SOA 上做的升华粒度更加细致，微服务架构强调的⼀个重点是<span style="color: rgb(227, 0, 0);">业务需要彻底的组件化和服务</span></div><div><br/></div><div><br/></div><div>微服务架构和SOA架构相似但又有不同</div><div>微服务架构和SOA架构很明显的一个区别就是服务拆分粒度的不同，但是对于拉勾的架构发展来 说，我们所看到的SOA阶段其实服务拆分粒度相对来说已经比较细了（超前哦！），所以上述拉勾SOA 到拉勾微服务，从服务拆分上来说变化并不大，只是引入了相对完整的新一代Spring Cloud微服务技 术。自然，上述我们看到的都是拉勾架构演变的阶段结果，每一个阶段其实都经历了很多变化，拉勾的 服务拆分其实也是走过了从粗到细，并非绝对的一步到位。</div><div>例如： 微服务架构和SOA架构很明显的一个区别就是服务拆分粒度的不同，但是对于拉勾的架构发展来 说，我们所看到的SOA阶段其实服务拆分粒度相对来说已经比较细了（超前哦！），所以上述拉勾SOA 到拉勾微服务，从服务拆分上来说变化并不大，只是引入了相对完整的新一代Spring Cloud微服务技 术。自然，上述我们看到的都是拉勾架构演变的阶段结果，每一个阶段其实都经历了很多变化，拉勾的 服务拆分其实也是走过了从粗到细，并非绝对的一步到位。</div><div><br/></div><div>微服务架构体现的思想及优缺点：</div><div>微服务架构设计的核心思想就是“微”，拆分的粒度相对比较小，这样的话单一职责、开发的耦合度 就会降低、微小的功能可以独立部署扩展、灵活性强，升级改造影响范围小。</div><div><br/></div><div><span style="font-weight: bold;">微服务架构的优点: 微服务架构和微服务</span></div><ol><li><div>微服务很小，便于特定业务功能的聚焦</div></li><li><div>微服务很小，每个微服务都可以被一个小团队单独实施（开发、测试、部署上线、运维），团队合 作一定程度解耦，便于实施敏捷开发</div></li><li><div>微服务很小，便于重用和模块之间的组装</div></li><li><div>微服务很独立，那么不同的微服务可以使用不同的语言开发，松耦合</div></li><li><div>微服务架构下，我们更容易引入新技术</div></li></ol><div><br/></div><div>微服务架构的缺点：</div><ol><li><div>微服务架构下，分布式复杂难以管理，当服务数量增加，管理将越加复杂；</div></li><li><div>微服务架构下，分布式链路跟踪难等；</div></li></ol><div><br/></div><div><br/></div><div>微服务架构中的核心概念：</div><div>服务注册：服务提供者将所提供服务的信息（服务器IP和端口、服务访问协议等）注册/登记到注册 中心</div><div>服务发现：服务消费者能够从注册中心获取到较为实时的服务列表，然后根究一定的策略选择一个 服务访问</div><div>负载均衡：将请求压力分配到多个服务器（应用服务器、数据库服务器等），以此来提高服务的性能、 可靠性</div><div>熔断即断路保护。微服务架构中，如果下游服务因访问压力过大而响应变慢或失败，上游服务为了 保护系统整体可用性，可以暂时切断对下游服务的调用。这种牺牲局部，保全整体的措施就叫做熔断。</div><div><br/></div><div>链路追踪 微服务架构越发流行，一个项目往往拆分成很多个服务，那么一次请求就需要涉及到很多个服务。不同 的微服务可能是由不同的团队开发、可能使用不同的编程语言实现、整个项目也有可能部署在了很多服 务器上（甚至百台、千台）横跨多个不同的数据中心。所谓链路追踪，就是对一次请求涉及的很多个服 务链路进行日志记录、性能监控</div><div><br/></div><div>API 网关：</div><div>微服务架构下，不同的微服务往往会有不同的访问地址，客户端可能需要调用多个服务的接口才能 完成一个业务需求</div><div>客户端直接与各个微服务通信的缺点:</div><ol><li><div>客户端需要调用不同的url地址，增加了维护调用难度</div></li><li><div>在一定的场景下，也存在跨域请求的问题（前后端分离就会碰到跨域问题，原本我们在后端采 用Cors就能解决，现在利用网关，那么就放在网关这层做好了）</div></li><li><div>每个微服务都需要进行单独的身份认证</div></li></ol><div><br/></div><div>API网关就可以较好的统一处理上述问题，API请求调用统一接入API网关层，由网关转发请 求。API网关更专注在安全、路由、流量等问题的处理上（微服务团队专注于处理业务逻辑即可）</div><div><br/></div><div>API功能：</div><ol><li><div>统一接入（路由）</div></li><li><div>安全防护（统一鉴权，负责网关访问身份认证验证，与“访问认证中心”通信，实际认证业务逻辑 交移“访问认证中心”处理</div></li><li><div>黑白名单（实现通过IP地址控制禁止访问网关功能，控制访问）</div></li><li><div>协议适配（实现通信协议校验、适配转换的功能）</div></li><li><div>流量管控（限流）</div></li><li><div>长短链接支持</div></li><li><div>容错能力（负载均衡）</div></li></ol><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><span style="color: rgb(227, 0, 0); font-family: 华文宋体; font-size: 24pt;">Spring Cloud</span></div><div><br/></div><div>Spring Cloud是一系列框架的有序集合（Spring Cloud是一个规范）， 开发服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等， 利用Spring Boot的开发便利性简化了微服务架构的开发（自动装配）</div><div><br/></div><div>Spring Cloud其实是一套规范，是一套用于构建微服务架构的规范，而不是一个 可以拿来即用的框架（所谓规范就是应该有哪些功能组件，然后组件之间怎么配合，共同完成什么事 情）。在这个规范之下第三方的Netflix公司开发了一些组件、Spring官方开发了一些框架/组件，包括第 三方的阿里巴巴开发了一套框架/组件集合Spring Cloud Alibaba，这些才是Spring Cloud规范的实现。</div><div><br/></div><div>Spring Cloud 规范及实现意图要解决的问题其实就是微服务架构实施过程中存在的一些问题，比如 微服务架构中的服务注册发现问题、网络问题（比如熔断场景）、统一认证安全授权问题、负载均衡问 题、链路追踪等问题。</div><div><br/></div><ol><li><div>Distributed/versioned configuration （分布式/版本化配置）</div></li><li><div>Service registration and discovery （服务注册和发现）</div></li><li><div>Routing （智能路由）</div></li><li><div>Service-to-service calls （服务调用）</div></li><li><div>Load balancing （负载均衡）</div></li><li><div>Circuit Breakers （熔断器）</div></li><li><div>Global locks （全局锁）</div></li><li><div>Leadership election and cluster state （ 选举与集群状态管理）</div></li><li><div>Distributed messaging （分布式消息传递平台）</div></li></ol><div><br/></div><div>Spring Cloud 架构： Spring Cloud是一个微服务相关规范，这个规范意图为搭建微服务架构提供一站式服 务，采用组件（框架）化机制定义一系列组件，各类组件针对性的处理微服务中的特定问题，这些组件 共同来构成Spring Cloud微服务技术栈</div><div><br/></div><div>Spring Cloud 核心组件： Spring Cloud 生态圈中的组件，按照发展可以分为第一代 Spring Cloud组件和第二代 Spring Cloud组件。</div><div><br/></div><div><br/></div><div><img src="SpringBoot&SpringCloud_files/Image [7].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div><img src="SpringBoot&SpringCloud_files/Image [8].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div>Spring Cloud中的各组件协同工作，才能够支持一个完整的微服务架构。比如</div><ol><li><div>注册中心负责服务的注册与发现，很好将各服务连接起来</div></li><li><div>API网关负责转发所有外来的请求</div></li><li><div>断路器负责监控服务之间的调用情况，连续多次失败进行熔断保护。</div></li><li><div>配置中心提供了统一的配置信息管理服务,可以实时的通知各个服务获取最新的配置信息</div></li></ol><div><br/></div><div><br/></div><div>Spring Cloud 与 Dubbo 对比： Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架，基于RPC调用，对于目前使用率较高的 Spring Cloud Netflix来说，它是基于HTTP的，所以效率上没有Dubbo高，但问题在于Dubbo体系的组 件不全，不能够提供一站式解决方案，比如服务注册与发现需要借助于Zookeeper等实现，而Spring Cloud Netflix则是真正的提供了一站式服务化解决方案，且有Spring大家族背景。</div><div><br/></div><div>Spring Cloud 与 Spring Boot 的关系： Spring Cloud 只是利用了Spring Boot 的特点，让我们能够快速的实现微服务组件开发，否则不使 用Spring Boot的话，我们在使用Spring Cloud时，每一个组件的相关Jar包都需要我们自己导入配置以 及需要开发人员考虑兼容性等各种情况。所以Spring Boot是我们快速把Spring Cloud微服务技术应用起 来的一种方式。</div><div><br/></div><div><br/></div><div>基于SpringBoot来构造工程环境</div><div>在编写Mapper接口开发时：继承 BaseMapper&lt;实体类&gt; ： 使用的Mybatis-plus组件，该组件是Mybatis的加强版， 能够与SpringBoot进行非常友好的整合，对比Mybatis框架只有使用便捷的改变，没有具体功能的改变</div><div><br/></div><div>在页面静态化微服务中使用RestTemplate调用商品微服务的商品状态接口时（Restful API 接 口）。在微服务分布式集群环境下会存在的问题</div><ol><li><div>在服务消费者中，我们把url地址硬编码到代码中，不方便后期维护。</div></li><li><div>服务提供者只有一个服务，即便服务提供者形成集群，服务消费者还需要自己实现负载均衡。</div></li><li><div>服务提供者只有一个服务，即便服务提供者形成集群，服务消费者还需要自己实现负载均衡。</div></li><li><div>服务消费者调用服务提供者时候，如果出现故障能否及时发现不向用户抛出异常页面？</div></li><li><div>RestTemplate这种请求调用方式是否还有优化空间？能不能类似于Dubbo那样玩？</div></li><li><div>这么多的微服务统一认证如何实现？</div></li><li><div>配置文件每次都修改好多个很麻烦！</div></li></ol><div><br/></div><div>上述分析出的问题，其实就是微服务架构中必然面临的一些问题：</div><ol><li><div>服务管理：自动注册与发现、状态监管</div></li><li><div>服务负载均衡</div></li><li><div>熔断</div></li><li><div>远程过程调用</div></li><li><div>网关拦截、路由转发</div></li><li><div>统一认证</div></li><li><div>集中式配置管理，配置信息实时自动更新</div></li></ol><div>这些问题，Spring Cloud 体系都有解决方案</div><div><br/></div><div><br/></div><div>第一代 Spring Cloud 核心组件：</div><div>Eureka服务注册中心：</div><div>常用的服务注册中心：Eureka、Nacos、Zookeeper、Consul</div><div>注意：服务注册中心本质上是为了解耦服务提供者和服务消费者。</div><div><br/></div><div>服务消费者 --&gt; 服务提供者</div><div>服务消费者 --&gt; 服务注册中心 --&gt; 服务提供者</div><div><br/></div><div><br/></div><div>注册中心实现原理： 分布式微服务架构中，服务注册中心用于存储服务提供者地址信息、服务发布相关的属性信息，消 费者通过主动查询和被动通知的方式获取服务提供者的地址信息，而不再需要通过硬编码方式得到提供 者的地址信息。消费者只需要知道当前系统发布了那些服务，而不需要知道服务具体存在于什么位置， 这就是透明化路由。</div><ol><li><div>服务提供者启动</div></li><li><div>服务提供者将相关服务信息主动注册到注册中心</div></li><li><div>服务消费者获取服务注册信息：</div></li><ol><li><div>pull模式：服务消费者可以主动拉取可用的服务提供者清单</div></li><li><div>push模式：服务消费者订阅服务（当服务提供者有变化时，注册中心也会主动推送更新后的 服务清单给消费者</div></li></ol><li><div>服务消费者直接调用服务提供者</div></li><li><div>另外，注册中心也需要完成服务提供者的健康监控，当发现服务提供者失效时需要及时剔除；</div></li></ol><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>Zookeeper与 Eureka对比</div><div><br/></div><div>Zookeeper： Dubbo + Zookeeper</div><div>Zookeeper它是一个分布式服务框架，是Apache Hadoop 的一个子项目，它主要是用来解决 分布式应用中经常遇到的一些数据管理问题，如：统一命名服务、状态同步服务、集群管理、分布 式应用配置项的管理等， 简单来说zookeeper本质 = 存储 + 监听通知。 Zookeeper 用来做服务注册中心，主要是因为它具有节点变更通知功能，只要客户端监听相 关服务节点，服务节点的所有变更，都能及时的通知到监听客户端，这样作为调用方只要使用 Zookeeper 的客户端就能实现服务节点的订阅和变更通知功能了，非常方便。另外，Zookeeper 可用性也可以，因为只要半数以上的选举节点存活，整个集群就是可用的，最少节点数为3。</div><div><br/></div><div>Eureka： 由Netflix开源，并被Pivatal集成到SpringCloud体系中，它是基于 RestfulAPI 风格开发的服务 注册与发现组件。</div><div><br/></div><div><br/></div><div>Nacos： Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。简单来说 Nacos 就是 注册中心 + 配置中心的组合，帮助我们解决微服务开发必会涉及到的服务注册 与发 现，服务配置，服务管理等问题。Nacos 是 Spring Cloud Alibaba 核心组件之一，负责服务注册 与发现，还有配置。</div><div><br/></div><div><br/></div><div>CAP： CAP定理又称CAP原则，指的是在一个分布式系统中，Consistency（一致性）、 Availability（可用 性）、Partition tolerance（分区容错性），最多只能同时三个特性中的两个，三者不可兼得。</div><div>P：分区容错性：分布式系统在遇到某节点或网络分区故障的时候，仍然能够对外提供满足一致性或可用 性的服务（一定的要满足的）</div><div>C：数据一致性</div><div>A：高可用</div><div>CAP不可能同时满足三个，要么是AP，要么是CP</div><div><br/></div><div><br/></div><div>Eureka 包含两个组件：Eureka Server 和 Eureka Client，Eureka Client是一个Java客户端，用于简化 与Eureka Server的交互；Eureka Server提供服务发现的能力，各个微服务启动时，会通过Eureka Client向Eureka Server 进行注册自己的信息（例如网络信息），Eureka Server会存储该服务的信息；</div><div><img src="SpringBoot&SpringCloud_files/Image [9].png" type="image/png" data-filename="Image.png"/></div><ol><li><div>每一个Eureka Server都是一个集群。</div></li><li><div>us-east-1c、us-east-1d，us-east-1e代表不同的区也就是不同的机房</div></li><li><div>Application Service作为服务提供者向Eureka Server中注册服务，Eureka Server接受到注 册事件会在集群和分区中进行数据同步，Application Client作为消费端（服务消费者）可以从Eureka Server中获取到服务注册信息，进行服务调用。</div></li><li><div>微服务启动后，会周期性地向Eureka Server发送心跳（默认周期为30秒，默认Eureka Server 90S会将还没有续约的给剔除）以续约自己的信息</div></li><li><div>Eureka Server在一定时间内没有接收到某个微服务节点的心跳，Eureka Server将会注销该微 服务节点（默认90秒）</div></li><li><div>每个Eureka Server同时也是Eureka Client，多个Eureka Server之间通过复制的方式完成服务 注册列表的同步</div></li><li><div>Eureka Client会缓存Eureka Server中的信息。即使所有的Eureka Server节点都宕掉，服务消 费者依然可以使用缓存中的信息找到服务提供者</div></li></ol><div>Eureka通过心跳检测、健康检查和客户端缓存等机制，提高系统的灵活性、可伸缩性和高可用性。</div><div><br/></div><div>搭建单例Eureka Server服务注册中心</div><div>实现步骤：</div><ol><li><div>单实例Eureka Server—&gt;访问管理界面</div></li><li><div>服务提供者（商品微服务注册到集群）</div></li><li><div>服务消费者（页面静态化微服务注册到Eureka/从Eureka Server获取服务信息）</div></li><li><div>完成调用</div></li></ol><div><br/></div><div>在启动类中添加@EnableEurekaServer： 声明本项目是一个Eureka服务</div><div><span style="background-color: #2b2b2b; color: #bbb529; font-family: 'Consolas'; font-size: 13.5pt;">@EnableDiscoveryClient</span> <span style="background-color: #2b2b2b; color: #808080; font-family: 'Consolas'; font-size: 13.5pt;">//</span><span style="background-color: #2b2b2b; color: #808080; font-family: 'Arial Unicode MS'; font-size: 13.5pt;">也是将当前项目表示为注册中心的客户端，将注册中心进行注册，可以在所有的服务注册中心环境下使用</span></div><div><span style="background-color: #2b2b2b; color: #bbb529; font-family: 'Consolas'; font-size: 13.5pt;">@EnableDiscoveryClient</span> <span style="background-color: #2b2b2b; color: #808080; font-family: 'Consolas'; font-size: 13.5pt;">//</span><span style="background-color: #2b2b2b; color: #808080; font-family: 'Arial Unicode MS'; font-size: 13.5pt;">也是将当前项目表示为注册中心的客户端，将注册中心进行注册，可以在所有的服务注册中心环境下使用</span></div><div><br/></div><div>在集群环境下：spring-application-name下的名称必须相同</div><div><br/></div><div>Eureka元数据详解</div><div>Eureka的元数据有两种：标准元数据和自定义元数据。</div><ol><li><div>标准元数据：主机名、IP地址、端口号等信息，这些信息都会被发布在服务注册表中，用于服务之 间的调用。</div></li><li><div>自定义元数据：可以使用eureka.instance.metadata-map配置，符合KEY/VALUE的存储格式。这 些元数据可以在远程客户端中访问。</div></li></ol><div>我们可以在程序中可以使用DiscoveryClient 获取指定微服务的所有元数据信息</div><div><br/></div><div>Eureka客户端详解： 服务提供者（也是Eureka客户端）要向EurekaServer注册服务，并完成服务续约等工作</div><div>服务注册详解（服务提供者）</div><ol><li><div>当我们导入了eureka-client依赖坐标，配置Eureka服务注册中心地址</div></li><li><div>服务在启动时会向注册中心发起注册请求，携带服务元数据信息</div></li><li><div>Eureka注册中心会把服务的信息保存在Map中。</div></li></ol><div>服务续约详解（服务提供者）</div><div>服务每隔30秒会向注册中心续约(心跳)一次（也称为报活），如果没有续约，租约在90秒后到期， 然后服务会被失效。每隔30秒的续约操作我们称之为心跳检测</div><ol><li><div>Eureka Client ：30S续约一次，在Eureka Server更新自己的状态 (Client端进行配置)</div></li><li><div>Eureka Server：90S还没有进行续约，将该微服务实例从服务注册表（Map）剔除 (Client端进行 配置)</div></li><li><div>Eureka Client： 30S拉取服务最新的注册表并缓存到本地 (Client端进行配置)</div></li></ol><div><br/></div><div>这两个配置不需要配置</div><div><br/></div><div><br/></div><div>获取服务列表（服务注册表）详解（服务消费者）： 每隔30秒服务会从注册中心中拉取一份服务列表，这个时间可以通过配置修改。往往不需要我们调 整</div><div><br/></div><div>Eureka服务端详解：</div><div>服务下线：</div><ol><li><div>当服务正常关闭操作时，会发送服务下线的REST请求给EurekaServer。</div></li><li><div>服务中心接受到请求后，将该服务置为下线状态</div></li></ol><div>失效剔除： Eureka Server会定时（间隔值是eureka.server.eviction-interval-timer-in-ms，默认60s）进行检 查，如果发现实例在在一定时间（此值由客户端设置的eureka.instance.lease-expiration-duration-inseconds定义，默认值为90s）内没有收到心跳，则会注销此实例。</div><div><br/></div><div>自我保护机制： 自我保护模式正是一种针对网络异常波动的安全保护措施，使用自我保护模式能使Eureka集群更加的 健壮、稳定的运行。</div><div>自我保护机制的工作机制： 如果在15分钟内超过85%的客户端节点都没有正常的心跳，那么 Eureka就认为客户端与注册中心出现了网络故障，Eureka Server自动进入自我保护机制，此时会出现 以下几种情况：</div><ol><li><div>Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。</div></li><li><div>Eureka Server仍然能够接受新服务的注册和查询请求，但是不会被同步到其它节点上，保证当前 节点依然可用。</div></li><li><div>当网络稳定时，当前Eureka Server新的注册信息会被同步到其它节点中。</div></li></ol><div><br/></div><div>因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况，而不会像ZK那样如果有一半 不可用的情况会导致整个集群不可用而变成瘫痪。</div><div><br/></div><div>自我保护机制好处： 默认情况下，如果Eureka Server在一定时间内（默认90秒）没有接收到某个微服务实例的心跳， Eureka Server将会移除该实例。但是当网络分区故障发生时，微服务与Eureka Server之间无法正常通 信，而微服务本身是正常运行的，此时不应该移除这个微服务，所以引入了自我保护机制。</div><div><font color="#FF0000">建议生产环境打开自我保护机制</font></div><div><br/></div><div><br/></div><div>Ribbon负载均衡：</div><div>负载均衡： 一般分为服务器端负载均衡和客户端负载均衡</div><div>服务器端负载均衡: 比如Nginx、F5这些，请求到达服务器之后由这些负载均衡器根据一定的 算法将请求路由到目标服务器处理。</div><div>客户端负载均衡: 比如我们要说的Ribbon，服务消费者客户端会有一个服务器地址列表，调用 方在请求前通过一定的负载均衡算法选择一个服务器进行访问，负载均衡算法的执行是在请求客户端进 行。</div><div>Ribbon是Netflix发布的负载均衡器。Eureka一般配合Ribbon进行使用，Ribbon利用从Eureka中读 取到服务信息，在调用服务提供者提供的服务时，会根据一定的算法进行负载。</div><div><br/></div><div><br/></div><div>在微服务中使用Ribbon不需要额外导入依赖坐标，微服务中引入过eureka-client相关依赖，会自动引入 Ribbon相关依赖坐标。</div><div><br/></div><div>在RestTemplate上添加 @LoadBalanced 注解即可</div><div><br/></div><div><br/></div><div>Ribbon负载均衡策略: Ribbon内置了多种负载均衡策略，内部负责复杂均衡的顶级接口为 <a href="http://com.netflix.loadbalancer.irule/">com.netflix.loadbalancer.IRule</a></div><div><img src="SpringBoot&SpringCloud_files/Image [10].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div>Hystrix熔断器: 属于一种容错机制</div><div><br/></div><div><br/></div><div>微服务中的雪崩效应:</div><div>微服务中，一个请求可能需要多个微服务接口才能实现，会形成复杂的调用链路。</div><div>服务雪崩效应：是一种因“服务提供者的不可用”（原因）导致“服务调用者不可用”（结果），并将不 可用逐渐放大的现象。</div><div>扇入：代表着该微服务被调用的次数，扇入大，说明该模块复用性好</div><div>扇出：该微服务调用其他微服务的个数，扇出大，说明业务逻辑复杂</div><div>扇入大是一个好事，扇出大不一定是好事</div><div>在微服务架构中，一个应用可能会有多个微服务组成，微服务之间的数据交互通过远程过程调用完 成。这就带来一个问题，假设微服务A调用微服务B和微服务C，微服务B和微服务C又调用其它的微服 务，这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应时间过长或者不可用，对微服务A的 调用就会占用越来越多的系统资源，进而引起系统崩溃，所谓的“雪崩效应”。</div><div><br/></div><div>雪崩效应形成原因：</div><div>服务雪崩的过程可以分为三个阶段：</div><ol><li><div>服务提供者不可用</div></li><li><div>重试加大请求流量</div></li><li><div>服务调用者不可用</div></li></ol><div>服务雪崩的每个阶段都可能由不同的原因造成：</div><div><img src="SpringBoot&SpringCloud_files/Image [11].png" type="image/png" data-filename="Image.png"/></div><div><br/></div><div><br/></div><div>雪崩效应解决方案: 服务熔断， 服务降级， 服务限流</div><div><br/></div><div><br/></div><div>服务熔断： 熔断机制是应对雪崩效应的一种微服务链路保护机制。我们在各种场景下都会接触到熔断这两个 字。高压电路中，如果某个地方的电压过高，熔断器就会熔断，对电路进行保护。股票交易中，如果股 票指数过高，也会采用熔断机制，暂停股票的交易。同样，在微服务架构中，熔断机制也是起着类似的 作用。当扇出链路的某个微服务不可用或者响应时间太长时，熔断该节点微服务的调用，进行服务的降 级，快速返回错误的响应信息。当检测到该节点微服务调用响应正常后，恢复调用链路。</div><div>注意：</div><ol><li><div>服务熔断重点在“断”，切断对下游服务的调用</div></li><li><div>服务熔断和服务降级往往是一起使用的，Hystrix就是这样。</div></li></ol><div>服务降级： 通俗讲就是整体资源不够用了，先将一些不关紧的服务停掉（调用我的时候，给你返回一个预留的 值，也叫做兜底数据），待渡过难关高峰过去，再把那些服务打开。 服务降级一般是从整体考虑，就是当某个服务熔断之后，服务器将不再被调用，此刻客户端可以自 己准备一个本地的fallback回调，返回一个缺省值，这样做，虽然服务水平下降，但好歹可用，比直接挂 掉要强。</div><div>服务限流：<span style="color: unset; font-family: unset; font-size: unset;">服务降级是当服务出问题或者影响到核心流程的性能时，暂时将服务屏蔽掉，待高峰或者问 题解决后再打开；但是有些场景并不能用服务降级来解决，比如秒杀业务这样的核心功能，这个时候可 以结合服务限流来限制这些场景的并发/请求量</span></div><div>限流措施也很多，比如：</div><ol><li><div>限制总并发数（比如数据库连接池、线程池）</div></li><li><div>限制瞬时并发数（如nginx限制瞬时并发连接数）</div></li><li><div>限制时间窗口内的平均速率（如Guava的RateLimiter、nginx的limit_req模块，限制每秒的平均速 率）</div></li><li><div>限制远程接口调用速率、限制MQ的消费速率等</div></li></ol><div><span style="color: unset; font-family: unset; font-size: unset;"><br/></span></div><div><br/></div><div>Hystrix主 要通过以下几点实现延迟和容错。</div><ol><li><div>包裹请求：使用HystrixCommand包裹对依赖的调用逻辑。 页面静态化微服务方法 （@HystrixCommand 添加Hystrix控制）</div></li><li><div>跳闸机制：当某服务的错误率超过一定的阈值时，Hystrix可以跳闸，停止请求该服务一段时间。</div></li><li><div>资源隔离：Hystrix为每个依赖都维护了一个小型的线程池(舱壁模式)。如果该线程池已满， 发往该 依赖的请求就被立即拒绝，而不是排队等待，从而加速失败判定。</div></li><li><div>监控：Hystrix可以近乎实时地监控运行指标和配置的变化，例如成功、失败、超时、以及被拒绝 的请求等</div></li><li><div>回退机制：当请求失败、超时、被拒绝，或当断路器打开时，执行回退逻辑。回退逻辑由开发人员 自行提供，例如返回一个缺省值。</div></li><li><div>自我修复：断路器打开一段时间后，会自动进入“半开”状态（探测服务是否可用，如还是不可用， 再次退回打开状态）。</div></li></ol><div><br/></div><div>熔断处理的目的是服务提供者长时间没有响应，服务消费者—&gt;页面静态化微服务快速失败给用户提示</div><div><br/></div><div>开启熔断： 服务消费者工程（静态化微服务）的启动类中添加熔断器开启注解 @EnableCircuitBreaker</div><div>定义服务降级处理方法：业务方法上使用@HystrixCommand的fallbackMethod属性关联到服务降 级处理方法</div><div>降级处理 配置@HystrixCommand注解，定义降级处理方法</div><div><br/></div><div>Hystrix舱壁模式： 线程池隔离策略</div><div>如果不进行任何设置，所有熔断方法使用一个Hystrix线程池（10个线程），那么这样的话会导致问题， 这个问题并不是扇出链路微服务不可用导致的，而是我们的线程机制导致的，如果方法A的请求把10个 线程都用了，方法2请求处理的时候压根都没法去访问B，因为没有线程可用，并不是B服务不可用。</div><div>为了避免问题服务请求过多导致正常服务无法访问，Hystrix 不是采用增加线程数，而是单独的为每一个 控制方法创建一个线程池的方式，这种模式叫做“舱壁模式&quot;，也是线程隔离的手段。</div><div><br/></div><div>Hystrix工作流程</div><ol><li><div>当调用出现问题时，开启一个时间窗（10s）</div></li><li><div>在这个时间窗内，统计调用次数是否达到最小请求数？ 如果没有达到，则重置统计信息，回到第1步， 如果达到了，则统计失败的请求数占所有请求数的百分比，是否达到阈值？ 如果达到，则跳闸（不再请求对应服务）， 如果达到，则跳闸（不再请求对应服务）</div></li><li><div>如果跳闸，则会开启一个活动窗口（默认5s），每隔5s，Hystrix会让一个请求通过,到达那个问题服 务，看是否调用成功，如果成功，重置断路器回到第1步，如果失败，回到第3步</div></li></ol><div><br/></div><div><br/></div><div>Feign远程调用组件</div><div><br/></div><div>Feign是Netflix开发的一个轻量级RESTful的HTTP服务客户端（用它来发起请求，远程调用的）， 是以Java接口注解的方式调用Http请求，而不用像Java中通过封装HTTP请求报文的方式直接调用， Feign被广泛应用在Spring Cloud 的解决方案中。 类似于Dubbo，服务消费者拿到服务提供者的接口，然后像调用本地接口方法一样去调用，实际发 出的是远程的请求。</div><ol><li><div>Feign可帮助我们更加便捷，优雅的调用HTTP API：不需要我们去拼接url然后呢调用restTemplate 的api，在SpringCloud中，使用Feign非常简单，创建一个接口（在消费者--服务调用方这一端）， 并在接口上添加一些注解，代码就完成了</div></li><li><div>SpringCloud对Feign进行了增强，使Feign支持了SpringMVC注解（OpenFeign）</div></li></ol><div>本质：封装了Http调用流程，更符合面向接口化的编程习惯，类似于Dubbo的服务调用</div><div><br/></div><div><font style="color: rgb(227, 0, 0);">Feign = RestTemplate+Ribbon+Hystrix</font></div><div><br/></div><div>服务消费者工程（静态化微服务）启动类使用注解@EnableFeignClients添加Feign支持</div><div>注意：此时去掉Hystrix熔断的支持注解@EnableCircuitBreaker即可包括引入的依赖，因为Feign会自动引入</div><div>在消费者微服务中创建Feign接口是最上面需要添加 @FeignClient(name = &quot;xxx&quot;)  xxx:服务提供者名称</div><div>注意： </div><ol><li><div>@FeignClient注解的name属性用于指定要调用的服务提供者名称，和服务提供者yml文件中 spring.application.name保持一致</div></li><li><div>接口中的接口方法，就好比是远程服务提供者Controller中的Hander方法（只不过如同本地调用 了），那么在进行参数绑定的时，可以使用@PathVariable、@RequestParam、@RequestHeader 等，这也是OpenFeign对SpringMVC注解的支持，但是需要注意value必须设置，否则会抛出异常</div></li><li><div>@FeignClient(name = &quot;lagou-service-product&quot;)，name在消费者微服务中只能出现一次。（升级 Spring Boot 2.1.0 Spring Cloud Greenwich.M1 版本后，在2个Feign接口类内定义相同的名字， @FeignClient(name = 相同的名字 就会出现报错，在之前的版本不会提示报错），所以最好将调用一个 微服务的信息都定义在一个Feign接口中。</div></li></ol><div><br/></div><div>Feign 本身已经集成了Ribbon依赖和自动配置，因此我们不需要额外引入依赖，可以通过 ribbon.xx 来进 行全局配置,也可以通过服务名.ribbon.xx 来对指定服务进行细节配置配置</div><div><br/></div><div>Feign默认的请求处理超时时长1s，有时候我们的业务确实执行的需要一定时间，那么这个时候，我们就 需要调整请求处理超时时长，Feign自己有超时设置，如果配置Ribbon的超时，则会以Ribbon的为准</div><div><br/></div><div>Feign对熔断器的支持： 在Feign客户端工程配置文件（application.yml）中开启Feign对熔断器的支持</div><div>Feign的超时时长设置那其实就是Ribbon的超时时长设置</div><div>Hystrix超时设置（按照之前Hystrix设置的方式就行）</div><div>注： 开启Hystrix之后，Feign中的方法都会被进行一个管理了，一旦出现问题就进入对应的回退逻辑处理， 针对超时这一点，当前有两个超时时间设置（Feign/hystrix），熔断的时候是根据这两个时间的最小 值来进行的，即处理时长超过最短的那个超时时间了就熔断进入回退降级逻辑</div><div><br/></div><div>Feign 支持对请求和响应进行GZIP压缩，以减少通信过程中的性能损耗。通过下面的参数 即可开启请求 与响应的压缩功能：</div><div><br/></div><div><br/></div><div>GateWay网关组件： Spring Cloud GateWay是Spring Cloud的一个全新项目，目标是取代Netflix Zuul，它基于 Spring5.0+SpringBoot2.0+WebFlux（基于高性能的Reactor模式响应式通信框架Netty，异步非阻塞模 型）等技术开发，性能高于Zuul，官方测试，GateWay是Zuul的1.6倍，旨在为微服务架构提供一种简 单有效的统一的API路由管理方式。 Spring Cloud GateWay不仅提供统一的路由方式（反向代理）并且基于 Filter(定义过滤器对请求过 滤，完成一些功能) 链的方式提供了网关基本的功能，例如：鉴权、流量控制、熔断、路径重写、日志监 控等。</div><div>网关：微服务架构中的重要组成部分</div><div><br/></div><div>网关在架构中的位置：客户端群 --&gt;负载均衡 --&gt; 网关集群 --&gt; 微服务</div><div><br/></div><div>GateWay核心概念： Spring Cloud GateWay天生就是异步非阻塞的，基于Reactor模型（同步非阻塞的I/O多路复用机 制）</div><div>一个请求—&gt;网关根据一定的条件匹配—匹配成功之后可以将请求转发到指定的服务地址；而在这 个过程中，我们可以进行一些比较具体的控制（限流、日志、黑白名单）</div><ol><li><div>路由（route）： 网关最基础的部分，也是网关比较基础的工作单元。路由由一个ID、一个目标 URL（最终路由到的地址）、一系列的断言（匹配条件判断）和Filter过滤器（精细化控制）组成。 如果断言为true，则匹配该路由。</div></li><li><div>断言（predicates）：参考了Java8中的断言java.util.function.Predicate，开发人员可以匹配Http 请求中的所有内容（包括请求头、请求参数等）（类似于nginx中的location匹配一样），如果断言 与请求相匹配则路由。</div></li><li><div>过滤器（filter）：一个标准的Spring webFilter，使用过滤器，可以在请求之前或者之后执行业务 逻辑。</div></li></ol><div><br/></div><div>GateWay工作： 客户端向Spring Cloud GateWay发出请求，然后在GateWay Handler Mapping中找到与请求相匹配 的路由，将其发送到GateWay Web Handler；Handler再通过指定的过滤器链来将请求发送到我们实际 的服务执行业务逻辑，然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送代理请求之前 （pre）或者之后（post）执行业务逻辑。</div><div>Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、日志输出、协议转换等，在“post” 类型的过滤器中可以做响应内容、响应头的修改、日志的输出、流量监控等。</div><div>Spring Cloud GateWay 帮我们内置了很多 Predicates功能，实现了各种路由匹配规则（通过 Header、请求参数等作为条件）匹配到对应的路由</div><div>动态路由设置时，uri以 lb: //开头（lb代表从注册中心获取服务），后面是需要转发到的服务名 称</div><div><br/></div><div>GateWay过滤器： 从过滤器生命周期（影响时机点）的角度来说，主要有两个pre和post：</div><div>pre ：这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选 择 请求的微服务、记录调试信息等。</div><div>post： 这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。</div><div>从过滤器类型的角度，Spring Cloud GateWay的过滤器分为GateWayFilter和GlobalFilter两种</div><div><img src="SpringBoot&SpringCloud_files/Image [12].png" type="image/png" data-filename="Image.png"/></div><div>Gateway Filter可以去掉url中的占位后转发路由</div><div><br/></div><div>注： GlobalFilter全局过滤器是程序员使用比较多的过滤器，我们主要讲解这种类型 5.7.2 自定义全局过滤器实现IP访问限制（黑白名单）， 请求过来时，判断发送请求的客户端的ip，如果在黑名单中，拒绝访问， 自定义GateWay全局过滤器时，我们实现Global Filter接口即可，通过全局过滤器可以实现黑白名 单、限流等功能。</div><div><br/></div><div>GateWay高可用： ：可以启动多个GateWay实例来实现高可用，在GateWay的上游使用 Nginx等负载均衡设备进行负载转发以达到高可用的目的。</div><div>启动多个GateWay实例（假如说两个，一个端口9002，一个端口9003），剩下的就是使用Nginx等 完成负载代理即可</div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>Spring Cloud Config 分布式配置中心</div><div>应用场景：</div><ol><li><div>集中配置管理，一个微服务架构中可能有成百上千个微服务，所以集中配置管理是很重要的 （一次修改、到处生效）</div></li><li><div>不同环境不同配置，比如数据源配置在不同环境（开发dev,测试test,生产prod）中是不同的</div></li><li><div>运行期间可动态调整。例如，可根据各个微服务的负载情况，动态调整数据源连接池大小等配 置修改后可自动更新</div></li><li><div>配置内容发生变化，微服务可以自动更新配置</div></li></ol><div>分布式配置中心的作用： 对配置文件进行集中式管理</div><div>Spring Cloud Config是一个分布式配置管理方案，包含了 Server端和 Client端两个部分。</div><ol><li><div>Server 端：提供配置文件的存储、以接口的形式将配置文件的内容提供出去，通过使用 @EnableConfigServer注解在 Spring boot 应用中非常简单的嵌入</div></li><li><div>Client 端：通过接口获取配置数据并初始化自己的应用</div></li></ol><div>Config分布式配置应用： Config Server是集中式的配置服务，用于集中管理应用程序各个环境下的配置。 默认使用 Git存储配置文件内容，也可以SVN。</div><ol><li><div>登录GitHub，创建项目</div></li><li><div>上传yml配置文件，命名规则如下： {application}-{profile}.yml 或者 {application}-{profile}.properties 其中，application为应用名称，profile指的是环境（用于区分开发环境，测试环境、生产环境 等）</div></li><li><div>构建Config Server统一配置中心， 新建SpringBoot工程，引入依赖坐标（需要注册自己到Eureka）</div></li></ol><div><br/></div><div>配置启动类，使用注解@EnableConfigServer开启配置中心服务器功</div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>微服务使用场景：项目足够庞大  面向的客户足够广泛</div><div><br/></div><div>springboot:就是实现了<span style="color: rgb(227, 0, 0);">约定优于配置(任何框架都可实现这种方式)</span>的这样的一种软件设计方式框架</div><div>两个核心作用：</div><ol><li><div>帮助我们管理依赖</div></li><li><div>进行自动配置</div></li></ol><div>controller通过路径访问需要定义容器</div><div><br/></div><div><span style="background-color: rgb(43, 43, 43); font-size: 13.5pt; color: rgb(169, 183, 198); font-family: Consolas;">@ComponentScan：启动组件扫描</span></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>rpc:远程调用过程，就是各个服务之间进行调用的协议</div><div>Eureka：服务注册中心</div><div><br/></div><div><br/></div><div>微服务架构中的核心概念</div><div><br/></div><div>假设有n个服务提供者 它们都需要把自己注册到服务注册中心 ，服务消费者同样也需要注册到服务者注册中心</div><div>注册完成后，当服务消费者需要调用服务时就可通过服务注册中心拉取服务提供者的列表，然后再根据需求去调用</div><div><br/></div><div>负载均衡：找较轻松的来干活</div><div><br/></div><div><br/></div><div><br/></div><div>静态页：由一个网页模板+商品的数据组成，电商系统每个商品上架时都会生成静态页(因为页面数据写死了所以访问效率高，不用去数据库动态获取数据)</div><div><br/></div><div><br/></div><div>页面静态化微服务调用的是商品微服务 所以不需要有service,mapper层 直接调用即可</div><div><br/></div><div>服务注册中心</div><div><br/></div><div>服务消费者去服务注册中心拉取服务提供者的信息 拿到信息后再去调用服务提供者</div><div><br/></div><div><br/></div><div>注册中心实现原理</div><div>启动服务注册中心-&gt;启动服务提供者(向服务注册中心进行注册)-&gt;启动服务消费者(将信息注册到服务注册中心)-&gt;服务消费者去服务注册中心获取服务提供者的信息(方式一：pull:从注册中心手动拉取可用的提供者清单；方式二：push:订阅服务，类似于订阅报纸/公众号， 当服务提供者有变化时，注册中心也会主动推送更新后的 服务清单给消费者 )</div><div>在服务消费者去调用服务提供者时需要考虑负载均衡的问题</div><div><br/></div><div><br/></div><div><br/></div><div>服务雪崩效应</div><div>服务不可用：缓存击穿 ：在程序中设置一级缓存 redie作为二级缓存 mysql   信息访问跳过缓存机制直接访问mysql数据库 造成缓存击穿</div><div>                    用户大量请求：可以用ngnix  Gateway网关  限流   令牌桶、漏桶算法解决</div><div><br/></div><div><br/></div><div>服务降级就是回滚操作</div><div><br/></div><div>降级处理就是一个回退方法</div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div>Feign远程调用组件的使用过程</div><ol><li><div>添加相关依赖</div></li><li><div>在启动类上开启Feign客户端功能 即使用@EnableFeignClients注解 这是可以注释掉启用熔断的注解</div></li><li><div>定义Feigin接口 头部添加@FeignClient注解 参数是调用目标的微服务名称</div></li><li><div>在具体的Controller中使用该接口调用具体的功能即可</div></li></ol><div><br/></div><div><br/></div><div><br/></div><div>开启Feign接口对熔断器的支持步骤：</div><ol><li><div>在配置中开启Feign的熔断功能</div></li><li><div>自定义回退逻辑</div></li><ol><li><div>写一个实现类实现feign接口</div></li><ol><li><div>在接口@FeignClien注解中添加一个fallback指定回调之后所用的类</div></li></ol></ol></ol><div><br/></div><div>网关服务夫最好和原有的微服务进行独立</div><div><br/></div><div>pre:</div><div>post:</div><div><br/></div><div><br/></div><div><br/></div><div>过滤器实现黑名单步骤：</div><ol><li><div>如果是黑名单 设置响应码 给错误提示  然后响应出去</div></li></ol><div><br/></div><div>实例数：同一个项目在集群下你部署了多少份</div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div><div><br/></div></div><div><br/></div></span>
</div></body></html> 